/**
 * 文档API管理模块
 * 负责与后端MinIO文档服务的接口对接
 */
class DocumentAPI {
  constructor() {
    this.baseURL = 'http://localhost:8080'; // 默认值
    this.timeout = 30000; // 默认超时时间
    this.isLocal = false; // 是否使用本地存储
    this.initConfig();
  }

  /**
   * 初始化配置
   */
  async initConfig() {
    try {
      // 等待配置管理器加载配置
      if (window.configManager) {
        await window.configManager.loadConfig();
        this.baseURL = window.configManager.getBackendBaseURL();
        this.timeout = window.configManager.getBackendTimeout();
        this.isLocal = window.configManager.getBackendConfig().islocal || false;
      }
    } catch (error) {
      console.warn('无法加载配置，使用默认值:', error);
    }
  }

  /**
   * 获取API基础URL
   */
  getAPIBaseURL() {
    return this.baseURL;
  }
  /**
   * 获取是否使用本地存储
   */
  isLocalMode() {
    return this.isLocal;
  }

  /**
   * 本地存储相关方法
   */
  
  /**
   * 从本地存储获取文档列表
   */
  getLocalDocuments() {
    try {
      const docs = localStorage.getItem('localDocuments');
      return docs ? JSON.parse(docs) : [];
    } catch (error) {
      console.error('读取本地文档失败:', error);
      return [];
    }
  }

  /**
   * 保存文档到本地存储
   */
  saveLocalDocuments(documents) {
    try {
      localStorage.setItem('localDocuments', JSON.stringify(documents));
    } catch (error) {
      console.error('保存本地文档失败:', error);
    }
  }

  /**
   * 生成本地文档ID
   */
  generateLocalId() {
    return Date.now() + Math.random().toString(36).substr(2, 9);
  }
  /**
   * 创建本地文档对象
   */
  createLocalDocument(file) {
    const id = this.generateLocalId();
    return {
      id: id,
      name: file.name,
      size: file.size,
      fileObjectName: `local_${id}_${file.name}`,
      url: URL.createObjectURL(file),
      vectorState: 'Initial',
      createTime: new Date().toISOString(),
      updateTime: new Date().toISOString()
    };
  }

  /**
   * 本地模式上传文件
   */
  async uploadFileLocal(file) {
    try {
      const documents = this.getLocalDocuments();
      const newDoc = this.createLocalDocument(file);
      
      documents.unshift(newDoc);
      this.saveLocalDocuments(documents);
      
      // 模拟异步操作
      await new Promise(resolve => setTimeout(resolve, 500));
      
      return newDoc;
    } catch (error) {
      console.error('本地上传文件失败:', error);
      throw new Error(`本地文件上传失败: ${error.message}`);
    }
  }

  /**
   * 本地模式获取文件列表
   */
  async listFilesLocal() {
    try {
      // 模拟异步操作
      await new Promise(resolve => setTimeout(resolve, 200));
      
      return this.getLocalDocuments();
    } catch (error) {
      console.error('本地获取文件列表失败:', error);
      throw new Error(`本地获取文件列表失败: ${error.message}`);
    }
  }

  /**
   * 本地模式删除文件
   */
  async deleteFileByIdLocal(id) {
    try {
      const documents = this.getLocalDocuments();
      const fileIndex = documents.findIndex(doc => doc.id === id);
      
      if (fileIndex === -1) {
        throw new Error('文件不存在');
      }
      
      const deletedDoc = documents[fileIndex];
      
      // 清理URL对象
      if (deletedDoc.url && deletedDoc.url.startsWith('blob:')) {
        URL.revokeObjectURL(deletedDoc.url);
      }
      
      documents.splice(fileIndex, 1);
      this.saveLocalDocuments(documents);
      
      // 模拟异步操作
      await new Promise(resolve => setTimeout(resolve, 300));
      
      return true;
    } catch (error) {
      console.error('本地删除文件失败:', error);
      throw new Error(`本地删除文件失败: ${error.message}`);
    }
  }
  /**
   * 创建带超时的 fetch 请求
   */
  async fetchWithTimeout(url, options = {}) {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), this.timeout);

    try {
      const response = await fetch(url, {
        ...options,
        signal: controller.signal
      });
      clearTimeout(timeoutId);
      return response;
    } catch (error) {
      clearTimeout(timeoutId);
      if (error.name === 'AbortError') {
        throw new Error('请求超时');
      }
      throw error;
    }
  }
  /**
   * 上传文件到MinIO
   */
  async uploadFile(file) {
    // 根据配置选择本地存储或远程API
    if (this.isLocal) {
      return await this.uploadFileLocal(file);
    }
    
    try {
      const formData = new FormData();
      formData.append('file', file);

      const response = await this.fetchWithTimeout(`${this.baseURL}/api/minio/uploadFile`, {
        method: 'POST',
        body: formData,
        headers: {
          // 不设置Content-Type，让浏览器自动设置multipart/form-data边界
        }
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const result = await response.json();
      
      // 检查响应格式
      if (result.success === false) {
        throw new Error(result.message || '上传失败');
      }

      return result.data || result;
    } catch (error) {
      console.error('上传文件失败:', error);
      throw new Error(`文件上传失败: ${error.message}`);
    }
  }  /**
   * 获取文件列表
   */
  async listFiles() {
    // 根据配置选择本地存储或远程API
    if (this.isLocal) {
      return await this.listFilesLocal();
    }
    
    try {
      const response = await this.fetchWithTimeout(`${this.baseURL}/api/minio/listFile`, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json'
        }
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const result = await response.json();
      
      // 检查响应格式
      if (result.success === false) {
        throw new Error(result.message || '获取文件列表失败');
      }

      return result.data || result || [];
    } catch (error) {
      console.error('获取文件列表失败:', error);
      throw new Error(`获取文件列表失败: ${error.message}`);
    }
  }
  /**
   * 根据ID删除文件
   */
  async deleteFileById(id) {
    // 根据配置选择本地存储或远程API
    if (this.isLocal) {
      return await this.deleteFileByIdLocal(id);
    }
    
    try {
      const response = await this.fetchWithTimeout(`${this.baseURL}/api/minio/deleteFileById`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ id })
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const result = await response.json();
      
      // 检查响应格式
      if (result.success === false) {
        throw new Error(result.message || '删除文件失败');
      }

      return result.data !== undefined ? result.data : result;
    } catch (error) {
      console.error('删除文件失败:', error);
      throw new Error(`删除文件失败: ${error.message}`);
    }
  }

  /**
   * 批量删除文件
   * @param {Array<string|number>} ids - 文件ID数组
   * @returns {Promise<Array<{id: string|number, success: boolean, error?: string}>>} 批量删除结果
   */
  async deleteFilesByIds(ids) {
    const results = [];
    
    for (const id of ids) {
      try {
        const success = await this.deleteFileById(id);
        results.push({ id, success });
      } catch (error) {
        results.push({ id, success: false, error: error.message });
      }
    }
    
    return results;
  }
  /**
   * 获取文件下载URL
   * @param {string|number} id - 文件ID
   * @returns {Promise<string>} 下载URL
   */
  async getFileDownloadUrl(id) {
    // 根据配置选择本地存储或远程API
    if (this.isLocal) {
      return await this.getFileDownloadUrlLocal(id);
    }
    
    try {
      const response = await this.fetchWithTimeout(`${this.baseURL}/api/minio/downloadFile`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ id })
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const result = await response.json();
      
      // 检查响应格式
      if (result.success === false) {
        throw new Error(result.message || '获取文件下载URL失败');
      }

      const fileData = result.data || result;
      
      // 返回文件的下载URL
      if (!fileData.url) {
        throw new Error('响应中缺少文件URL');
      }
      
      return fileData.url;
    } catch (error) {
      console.error('获取文件下载URL失败:', error);
      throw new Error(`获取文件下载URL失败: ${error.message}`);
    }
  }

  /**
   * 本地模式获取文件下载URL
   * @param {string|number} id - 文件ID
   * @returns {Promise<string>} 下载URL
   */
  async getFileDownloadUrlLocal(id) {
    try {
      // 首先获取文件信息
      const files = await this.listFilesLocal();
      const file = files.find(f => f.id == id);
      
      if (!file) {
        throw new Error('文件不存在');
      }
      
      return file.url;
    } catch (error) {
      console.error('本地获取文件下载URL失败:', error);
      throw new Error(`本地获取文件下载URL失败: ${error.message}`);
    }
  }

  /**
   * 检查文件是否存在
   * @param {string|number} id - 文件ID
   * @returns {Promise<boolean>} 文件是否存在
   */
  async fileExists(id) {
    try {
      const files = await this.listFiles();
      return files.some(f => f.id == id);
    } catch (error) {
      console.error('检查文件是否存在失败:', error);
      return false;
    }
  }

  /**
   * 根据名称搜索文件
   * @param {string} name - 文件名称（支持模糊搜索）
   * @returns {Promise<Array<UploadFileVo>>} 匹配的文件列表
   */
  async searchFilesByName(name) {
    try {
      const files = await this.listFiles();
      const searchTerm = name.toLowerCase();
      
      return files.filter(file => 
        file.name && file.name.toLowerCase().includes(searchTerm)
      );
    } catch (error) {
      console.error('搜索文件失败:', error);
      throw new Error(`搜索文件失败: ${error.message}`);
    }
  }

  /**
   * 根据向量化状态筛选文件
   * @param {string} vectorState - 向量化状态 (pending, processing, completed, failed)
   * @returns {Promise<Array<UploadFileVo>>} 匹配状态的文件列表
   */
  async getFilesByVectorState(vectorState) {
    try {
      const files = await this.listFiles();
      
      return files.filter(file => 
        file.vectorState === vectorState
      );
    } catch (error) {
      console.error('根据向量化状态筛选文件失败:', error);
      throw new Error(`根据向量化状态筛选文件失败: ${error.message}`);
    }
  }

  /**
   * 格式化文件大小
   * @param {number} bytes - 字节数
   * @returns {string} 格式化后的文件大小
   */
  formatFileSize(bytes) {
    if (bytes === 0) return '0 B';

    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));

    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
  }

  /**
   * 格式化日期时间
   * @param {string} dateTimeString - ISO日期时间字符串
   * @returns {string} 格式化后的日期时间
   */
  formatDateTime(dateTimeString) {
    if (!dateTimeString) return '';
    
    const date = new Date(dateTimeString);
    return date.toLocaleString('zh-CN', {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit'
    });
  }
  /**
   * 获取向量化状态的显示文本
   * @param {string} vectorState - 向量化状态
   * @returns {string} 状态显示文本
   */
  getVectorStateText(vectorState) {
    const stateMap = {
      'Initial': '未向量化',
      'Successful': '向量化完成',
      'Failed': '向量化失败',
      'pending': '待处理',
      'processing': '处理中',
      'completed': '已完成',
      'failed': '失败'
    };
    return stateMap[vectorState] || '未知';
  }
  /**
   * 获取向量化状态的CSS类名
   * @param {string} vectorState - 向量化状态
   * @returns {string} CSS类名
   */
  getVectorStateClass(vectorState) {
    return `vector-state-${vectorState}`;
  }

  /**
   * 切换到本地模式
   */
  switchToLocalMode() {
    this.isLocal = true;
    if (window.configManager) {
      window.configManager.setLocalMode(true);
    }
    console.log('已切换到本地存储模式');
  }

  /**
   * 切换到远程API模式
   */
  switchToRemoteMode() {
    this.isLocal = false;
    if (window.configManager) {
      window.configManager.setLocalMode(false);
    }
    console.log('已切换到远程API模式');
  }

  /**
   * 获取当前模式信息
   */
  getCurrentMode() {
    return {
      isLocal: this.isLocal,
      mode: this.isLocal ? 'localStorage' : 'remote-api',
      baseURL: this.isLocal ? 'localStorage' : this.baseURL
    };
  }

  /**
   * 清理本地存储数据
   */
  clearLocalStorage() {
    try {
      // 清理文档URL对象
      const documents = this.getLocalDocuments();
      documents.forEach(doc => {
        if (doc.url && doc.url.startsWith('blob:')) {
          URL.revokeObjectURL(doc.url);
        }
      });
      
      // 清除本地存储
      localStorage.removeItem('localDocuments');
      console.log('本地存储数据已清理');
    } catch (error) {
      console.error('清理本地存储失败:', error);
    }
  }

  /**
   * 数据迁移：从本地存储到远程API
   */
  async migrateFromLocalToRemote() {
    if (this.isLocal) {
      throw new Error('当前处于本地模式，无法迁移');
    }

    try {
      const localDocs = this.getLocalDocuments();
      if (localDocs.length === 0) {
        console.log('没有本地数据需要迁移');
        return [];
      }

      console.log(`开始迁移 ${localDocs.length} 个文档到远程服务器...`);
      const results = [];

      for (const doc of localDocs) {
        try {
          // 这里需要从blob URL重新获取文件数据，实际实现可能需要调整
          console.log(`正在迁移文档: ${doc.name}`);
          // 注意：实际迁移需要重新上传文件，这里只是示例
          results.push({ success: true, document: doc });
        } catch (error) {
          console.error(`迁移文档 ${doc.name} 失败:`, error);
          results.push({ success: false, document: doc, error: error.message });
        }
      }

      console.log('数据迁移完成');
      return results;
    } catch (error) {
      console.error('数据迁移失败:', error);
      throw error;
    }
  }

  /**
   * 向量化文件
   * @param {string|number} id - 文件ID
   * @returns {Promise<UploadFileVo>} 向量化结果
   */
  async vectorizeFile(id) {
    // 本地模式不支持向量化
    if (this.isLocal) {
      throw new Error('本地模式不支持文件向量化');
    }
    
    try {
      const response = await this.fetchWithTimeout(`${this.baseURL}/api/minio/vectorFile`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ id })
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const result = await response.json();
      
      // 检查响应格式
      if (result.success === false) {
        throw new Error(result.message || '向量化文件失败');
      }

      return result.data !== undefined ? result.data : result;
    } catch (error) {
      console.error('向量化文件失败:', error);
      throw new Error(`向量化文件失败: ${error.message}`);
    }
  }
}

// 创建全局实例
window.documentAPI = new DocumentAPI();

// 导出类
window.DocumentAPI = DocumentAPI;
